package com.mcxtzhang.lib;

import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.Path;
import ohos.agp.render.Region;
import ohos.agp.utils.Color;
import ohos.agp.utils.Rect;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;
import ohos.multimodalinput.event.TouchEvent;

/**
 * 介绍：仿饿了么购物车加减Button
 * 自带闪转腾挪动画
 * <p>
 * 项目地址：https://github.com/mcxtzhang/AnimShopButton
 * <p>
 * 作者：zhangxutong
 * 邮箱：mcxtzhang@163.com
 * 主页：http://blog.csdn.net/zxt0601
 * 时间： 2016/11/18.
 * 历史：
 * Version : 1.1.0 Time: 2017/01/12
 * 1 Feature : 增加一个开关 ignoreHintArea ：UI显示、动画是否忽略hint收缩区域
 * 2 Feature : 增加一个int变量 perAnimDuration : 对每段动画的duration的设置方法
 * Version : 1.2.0 Time: 2017/02/08
 * 1 Feature : 增加一个状态，正在补货中，此时不允许点击
 * 通过setReplenish(boolean )和isReplenish()设置判断
 */

public class AnimShopButton extends Component implements
        Component.DrawTask,
        Component.EstimateSizeListener,
        Component.TouchEventListener,
        Component.LayoutRefreshedListener {
    protected static final String TAG = "zxt/" + AnimShopButton.class.getName();
    protected static final int DEFAULT_DURATION = 350;
    //控件 paddingLeft paddingTop + paint的width
    protected int mLeft, mTop;
    //宽高
    protected int mWidth, mHeight;


    //加减的圆的Path的Region
    protected Region mAddRegion, mDelRegion;
    protected Path mAddPath, mDelPath;

    /**
     * 加按钮
     */
    protected Paint mAddPaint;
    //加按钮是否开启fill模式 默认是stroke(xml)(false)
    protected boolean isAddFillMode;
    //加按钮的背景色前景色(xml)
    protected int mAddEnableBgColor;
    protected Color mAddEnableFgColor;
    //加按钮不可用时的背景色前景色(xml)
    protected int mAddDisableBgColor;
    protected Color mAddDisableFgColor;

    /**
     * 减按钮
     */
    protected Paint mDelPaint;
    //按钮是否开启fill模式 默认是stroke(xml)(false)
    protected boolean isDelFillMode;
    //按钮的背景色前景色(xml)
    protected int mDelEnableBgColor;
    protected int mDelEnableFgColor;
    //按钮不可用时的背景色前景色(xml)
    protected int mDelDisableBgColor;
    protected int mDelDisableFgColor;

    //最大数量和当前数量(xml)
    protected int mMaxCount;
    protected int mCount;

    //圆的半径
    protected float mRadius;
    //圆圈的宽度
    protected float mCircleWidth;
    //线的宽度
    protected float mLineWidth;


    /**
     * 两个圆之间的间距(xml)
     */
    protected float mGapBetweenCircle;
    //绘制数量的textSize
    protected float mTextSize;
    protected Paint mTextPaint;
    protected Paint.FontMetrics mFontMetrics;

    //动画的基准值 动画：减 0~1, 加 1~0 ,
    // 普通状态下都显示时是0
    protected AnimatorValue mAnimAdd, mAniDel;
    protected float mAnimFraction;

    //展开 加入购物车动画
    protected AnimatorValue mAnimExpandHint;
    protected AnimatorValue mAnimReduceHint;

    protected int mPerAnimDuration = DEFAULT_DURATION;

    /**
     * 增加一个开关 ignoreHintArea：UI显示、动画是否忽略hint收缩区域
     */
    protected boolean ignoreHintArea;

    //是否处于HintMode下 count = 0 时，且第一段收缩动画做完了，是true
    protected boolean isHintMode;

    //提示语收缩动画 0-1 展开1-0
    //普通模式时，应该是1， 只在 isHintMode true 才有效
    protected float mAnimExpandHintFraction;

    //展开动画结束后 才显示文字
    protected boolean isShowHintText;

    //数量为0时，hint文字 背景色前景色(xml) 大小
    protected Paint mHintPaint;
    protected int mHintBgColor;
    protected int mHingTextSize;
    protected String mHintText;
    protected Color mHintFgColor;
    /**
     * 圆角值(xml)
     */
    protected int mHintBgRoundValue;

    //Feature : 显示正在补货中，此时不允许点击
    protected boolean isReplenish;
    //画笔、颜色、大小、文字
    protected Paint mReplenishPaint;
    protected int mReplenishTextColor;
    protected int mReplenishTextSize;
    protected String mReplenishText;


    //点击回调
    protected IOnAddDelListener mOnAddDelListener;

    public AnimShopButton(Context context) {
        this(context, null);
    }

    public AnimShopButton(Context context, AttrSet attrs) {
        this(context, attrs, 0);
    }

    public AnimShopButton(Context context, AttrSet attrSet, int resId) {
        super(context, attrSet, resId);
        init(context, attrSet, resId);
        setEstimateSizeListener(this::onEstimateSize);
        addDrawTask(this);
        setTouchEventListener(this::onTouchEvent);
    }

    public int getCount() {
        return mCount;
    }

    /**
     * 设置当前数量
     *
     * @param count
     * @return
     */
    public AnimShopButton setCount(int count) {
        mCount = count;
        //先暂停所有动画
        cancelAllAnim();

        //复用机制的处理

        initAnimSettingsByCount();
        return this;
    }

    /**
     * 暂停所有动画
     */
    private void cancelAllAnim() {
        if (mAnimAdd != null && mAnimAdd.isRunning()) {
            mAnimAdd.cancel();
        }
        if (mAniDel != null && mAniDel.isRunning()) {
            mAniDel.cancel();
        }
        if (mAnimExpandHint != null && mAnimExpandHint.isRunning()) {
            mAnimExpandHint.cancel();
        }
        if (mAnimReduceHint != null && mAnimReduceHint.isRunning()) {
            mAnimReduceHint.cancel();
        }
    }

    public IOnAddDelListener getOnAddDelListener() {
        return mOnAddDelListener;
    }

    public int getMaxCount() {
        return mMaxCount;
    }

    /**
     * 设置最大数量
     *
     * @param maxCount
     * @return
     */
    public AnimShopButton setMaxCount(int maxCount) {
        mMaxCount = maxCount;
        return this;
    }

    public boolean isReplenish() {
        return isReplenish;
    }

    public AnimShopButton setReplenish(boolean replenish) {
        isReplenish = replenish;
        if (isReplenish && null == mReplenishPaint) {
            mReplenishPaint = new Paint();
            mReplenishPaint.setAntiAlias(true);
            mReplenishPaint.setTextSize(mReplenishTextSize);
            mReplenishPaint.setColor(new Color(mReplenishTextColor));
        }
        return this;
    }

    public int getReplenishTextColor() {
        return mReplenishTextColor;
    }

    public AnimShopButton setReplenishTextColor(int replenishTextColor) {
        mReplenishTextColor = replenishTextColor;
        return this;
    }

    public int getReplenishTextSize() {
        return mReplenishTextSize;
    }

    public AnimShopButton setReplenishTextSize(int replenishTextSize) {
        mReplenishTextSize = replenishTextSize;
        return this;
    }

    public String getReplenishText() {
        return mReplenishText;
    }

    public AnimShopButton setReplenishText(String replenishText) {
        mReplenishText = replenishText;
        return this;
    }

    public boolean isAddFillMode() {
        return isAddFillMode;
    }

    public AnimShopButton setAddFillMode(boolean addFillMode) {
        isAddFillMode = addFillMode;
        return this;
    }

    public int getAddEnableBgColor() {
        return mAddEnableBgColor;
    }

    public AnimShopButton setAddEnableBgColor(int addEnableBgColor) {
        mAddEnableBgColor = addEnableBgColor;
        return this;
    }

    public Color getAddEnableFgColor() {
        return mAddEnableFgColor;
    }

    public AnimShopButton setAddEnableFgColor(Color addEnableFgColor) {
        mAddEnableFgColor = addEnableFgColor;
        return this;
    }

    public int getAddDisableBgColor() {
        return mAddDisableBgColor;
    }

    public AnimShopButton setAddDisableBgColor(int addDisableBgColor) {
        mAddDisableBgColor = addDisableBgColor;
        return this;
    }

    public Color getAddDisableFgColor() {
        return mAddDisableFgColor;
    }

    public AnimShopButton setAddDisableFgColor(Color addDisableFgColor) {
        mAddDisableFgColor = addDisableFgColor;
        return this;
    }

    public boolean isDelFillMode() {
        return isDelFillMode;
    }

    public AnimShopButton setDelFillMode(boolean delFillMode) {
        isDelFillMode = delFillMode;
        return this;
    }

    public int getDelEnableBgColor() {
        return mDelEnableBgColor;
    }

    public AnimShopButton setDelEnableBgColor(int delEnableBgColor) {
        mDelEnableBgColor = delEnableBgColor;
        return this;
    }

    public int getDelEnableFgColor() {
        return mDelEnableFgColor;
    }

    public AnimShopButton setDelEnableFgColor(int delEnableFgColor) {
        mDelEnableFgColor = delEnableFgColor;
        return this;
    }

    public int getDelDisableBgColor() {
        return mDelDisableBgColor;
    }

    public AnimShopButton setDelDisableBgColor(int delDisableBgColor) {
        mDelDisableBgColor = delDisableBgColor;
        return this;
    }

    public int getDelDisableFgColor() {
        return mDelDisableFgColor;
    }

    public AnimShopButton setDelDisableFgColor(int delDisableFgColor) {
        mDelDisableFgColor = delDisableFgColor;
        return this;
    }

    public float getRadius() {
        return mRadius;
    }

    public AnimShopButton setRadius(float radius) {
        mRadius = radius;
        return this;
    }

    public float getCircleWidth() {
        return mCircleWidth;
    }

    public AnimShopButton setCircleWidth(float circleWidth) {
        mCircleWidth = circleWidth;
        return this;
    }

    public float getLineWidth() {
        return mLineWidth;
    }

    public AnimShopButton setLineWidth(float lineWidth) {
        mLineWidth = lineWidth;
        return this;
    }

    public float getTextSize() {
        return mTextSize;
    }

    public AnimShopButton setTextSize(float textSize) {
        mTextSize = textSize;
        return this;
    }

    public float getGapBetweenCircle() {
        return mGapBetweenCircle;
    }

    public AnimShopButton setGapBetweenCircle(float gapBetweenCircle) {
        mGapBetweenCircle = gapBetweenCircle;
        return this;
    }

    public int getPerAnimDuration() {
        return mPerAnimDuration;
    }

    public AnimShopButton setPerAnimDuration(int perAnimDuration) {
        mPerAnimDuration = perAnimDuration;
        return this;
    }

    public boolean isIgnoreHintArea() {
        return ignoreHintArea;
    }

    public AnimShopButton setIgnoreHintArea(boolean ignoreHintArea) {
        this.ignoreHintArea = ignoreHintArea;
        return this;
    }

    public int getHintBgColor() {
        return mHintBgColor;
    }

    public AnimShopButton setHintBgColor(int hintBgColor) {
        mHintBgColor = hintBgColor;
        return this;
    }

    public int getHingTextSize() {
        return mHingTextSize;
    }

    public AnimShopButton setHingTextSize(int hingTextSize) {
        mHingTextSize = hingTextSize;
        return this;
    }

    public String getHintText() {
        return mHintText;
    }

    public AnimShopButton setHintText(String hintText) {
        mHintText = hintText;
        return this;
    }

    public Color getHintFgColor() {
        return mHintFgColor;
    }

    public AnimShopButton setHintFgColor(Color hintFgColor) {
        mHintFgColor = hintFgColor;
        return this;
    }

    public int getHintBgRoundValue() {
        return mHintBgRoundValue;
    }

    public AnimShopButton setHintBgRoundValue(int hintBgRoundValue) {
        mHintBgRoundValue = hintBgRoundValue;
        return this;
    }

    /**
     * 设置加减监听器
     *
     * @param IOnAddDelListener
     * @return
     */
    public AnimShopButton setOnAddDelListener(IOnAddDelListener IOnAddDelListener) {
        mOnAddDelListener = IOnAddDelListener;
        return this;
    }

    protected void init(Context context, AttrSet attrs, int resId) {

        //模拟参数传入(设置初始值)
        initDefaultValue(context);
        //end

        if (attrs != null) {
            mGapBetweenCircle =
                    AttrSetUtils.optPixelSize(attrs, "gapBetweenCircle", mGapBetweenCircle);
            isAddFillMode = AttrSetUtils.optBoolean(attrs, "isAddFillMode", isAddFillMode);
            mAddEnableBgColor = AttrSetUtils.optColor(attrs, "addEnableBgColor", mAddEnableBgColor);
            mAddEnableFgColor = new Color(AttrSetUtils
                    .optColor(attrs, "addEnableFgColor", mAddEnableFgColor.getValue()));
            mAddDisableBgColor = AttrSetUtils
                    .optColor(attrs, "addDisableBgColor", mAddDisableBgColor);
            mAddDisableFgColor = new Color(AttrSetUtils
                    .optColor(attrs, "addDisableFgColor", mAddDisableFgColor.getValue()));
            isDelFillMode = AttrSetUtils.optBoolean(attrs, "isDelFillMode", isDelFillMode);
            mDelEnableBgColor = AttrSetUtils
                    .optColor(attrs, "delEnableBgColor", mDelEnableBgColor);
            mDelEnableFgColor = AttrSetUtils
                    .optColor(attrs, "delEnableFgColor", mDelEnableFgColor);
            mDelDisableBgColor = AttrSetUtils
                    .optColor(attrs, "delDisableBgColor", mDelDisableBgColor);
            mDelDisableFgColor = AttrSetUtils
                    .optColor(attrs, "delDisableFgColor", mDelDisableFgColor);
            mMaxCount = AttrSetUtils.optInt(attrs, "maxCount", mMaxCount);
            mCount = AttrSetUtils.optInt(attrs, "count", mCount);
            mRadius = AttrSetUtils.optPixelSize(attrs, "radius", mRadius);
            mCircleWidth = AttrSetUtils
                    .optPixelSize(attrs, "circleStrokeWidth", mCircleWidth);
            mLineWidth = AttrSetUtils.optPixelSize(attrs, "lineWidth", mLineWidth);
            mTextSize = AttrSetUtils.optPixelSize(attrs, "numTextSize", mTextSize);
            mHintText = AttrSetUtils.optString(attrs, "hintText", "加入购物车");
            mHintBgColor = AttrSetUtils.optColor(attrs, "hintBgColor", mHintBgColor);
            mHintFgColor = new Color(AttrSetUtils.optColor(attrs, "hintFgColor", mHintFgColor.getValue()));
            mHingTextSize = AttrSetUtils.optPixelSize(attrs, "hingTextSize", mHingTextSize);
            mHintBgRoundValue = AttrSetUtils.optPixelSize(attrs, "hintBgRoundValue", mHintBgRoundValue);
            ignoreHintArea = AttrSetUtils.optBoolean(attrs, "ignoreHintArea", false);
            mPerAnimDuration = AttrSetUtils.optInt(attrs, "perAnimDuration", DEFAULT_DURATION);
            mReplenishText = AttrSetUtils.optString(attrs, "replenishText", "补货中");
            mReplenishTextColor = AttrSetUtils.optColor(attrs, "replenishTextColor", mReplenishTextColor);
            mReplenishTextSize = AttrSetUtils.optPixelSize(attrs, "replenishTextSize", mReplenishTextSize);

        }

        mAddRegion = new Region();
        mDelRegion = new Region();
        mAddPath = new Path();
        mDelPath = new Path();

        mAddPaint = new Paint();
        mAddPaint.setAntiAlias(true);
        if (isAddFillMode) {
            mAddPaint.setStyle(Paint.Style.FILL_STYLE);
        } else {
            mAddPaint.setStyle(Paint.Style.STROKE_STYLE);
        }
        mDelPaint = new Paint();
        mDelPaint.setAntiAlias(true);
        if (isDelFillMode) {
            mDelPaint.setStyle(Paint.Style.FILL_STYLE);
        } else {
            mDelPaint.setStyle(Paint.Style.STROKE_STYLE);
        }

        mHintPaint = new Paint();
        mHintPaint.setAntiAlias(true);
        mHintPaint.setStyle(Paint.Style.FILL_STYLE);
        mHintPaint.setTextSize(mHingTextSize);


        mTextPaint = new Paint();
        mTextPaint.setAntiAlias(true);
        mTextPaint.setTextSize((int) mTextSize);
        mFontMetrics = mTextPaint.getFontMetrics();


        //动画 +
        mAnimAdd = MyValueAnimator.ofFloat(1, 0);
        mAnimAdd.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animatorValue, float v) {
                mAnimFraction = v;
                invalidate();
            }
        });
        mAnimAdd.setStateChangedListener(new Animator.StateChangedListener() {
            @Override
            public void onStart(Animator animator) {

            }

            @Override
            public void onStop(Animator animator) {

            }

            @Override
            public void onCancel(Animator animator) {

            }

            @Override
            public void onEnd(Animator animator) {

            }

            @Override
            public void onPause(Animator animator) {

            }

            @Override
            public void onResume(Animator animator) {

            }
        });
        mAnimAdd.setDuration(mPerAnimDuration);

        //提示语收缩动画 0-1
        mAnimReduceHint = MyValueAnimator.ofFloat(0,1);
        mAnimReduceHint.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animatorValue, float v) {
                LogUtil.debug("YC1022", "  mAnimReduceHint  v = " + v);
//                mAnimExpandHintFraction = getAnimatedValue(v, 1f);
                mAnimExpandHintFraction = v;
                invalidate();
            }
        });
        mAnimReduceHint.setStateChangedListener(new Animator.StateChangedListener() {
            @Override
            public void onStart(Animator animator) {
                if (mCount == 1) {
                    //先不显示文字了
                    isShowHintText = false;
                }
            }

            @Override
            public void onStop(Animator animator) {

            }

            @Override
            public void onCancel(Animator animator) {

            }

            @Override
            public void onEnd(Animator animator) {
                if (mCount >= 1) {
                    //然后底色也不显示了
                    isHintMode = false;
                }
                if (mCount >= 1) {
                    LogUtil.debug(TAG, "现在还是》=1 开始收缩动画");
                    if (mAnimAdd != null && !mAnimAdd.isRunning()) {
                        mAnimAdd.start();
                    }
                }
            }

            @Override
            public void onPause(Animator animator) {

            }

            @Override
            public void onResume(Animator animator) {

            }
        });
        mAnimReduceHint.setDuration(ignoreHintArea ? 0 : mPerAnimDuration);


        //动画 -
        mAniDel = MyValueAnimator.ofFloat(0, 1);
        mAniDel.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animatorValue, float v) {
//                mAnimFraction = getAnimatedValue(v, 1f);
                mAnimFraction = v;
                invalidate();
            }
        });
        //1-0的动画
        mAniDel.setStateChangedListener(new Animator.StateChangedListener() {
            @Override
            public void onStart(Animator animator) {

            }

            @Override
            public void onStop(Animator animator) {

            }

            @Override
            public void onCancel(Animator animator) {

            }

            @Override
            public void onEnd(Animator animator) {
                if (mCount == 0) {
                    LogUtil.debug(TAG, "现在还是0onAnimationEnd() " +
                            "called with: animation = [" + animator + "]");
                    if (mAnimExpandHint != null && !mAnimExpandHint.isRunning()) {
                        mAnimExpandHint.start();
                    }
                }
            }

            @Override
            public void onPause(Animator animator) {

            }

            @Override
            public void onResume(Animator animator) {

            }
        });
        mAniDel.setDuration(mPerAnimDuration);
        //提示语展开动画
        //分析这个动画，最初是个圆。 就是left 不断减小
        mAnimExpandHint = MyValueAnimator.ofFloat(1,0);
        mAnimExpandHint.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animatorValue, float v) {
                LogUtil.debug("YC1022", " mAnimExpandHint  v = " + v);
//                mAnimExpandHintFraction = getAnimatedValue(v, 0f);
                mAnimExpandHintFraction = v;
                invalidate();
            }
        });
        mAnimExpandHint.setStateChangedListener(new Animator.StateChangedListener() {
            @Override
            public void onStart(Animator animator) {
                if (mCount == 0) {
                    isHintMode = true;
                }
            }

            @Override
            public void onStop(Animator animator) {

            }

            @Override
            public void onCancel(Animator animator) {

            }

            @Override
            public void onEnd(Animator animator) {
                if (mCount == 0) {
                    isShowHintText = true;
                }
            }

            @Override
            public void onPause(Animator animator) {

            }

            @Override
            public void onResume(Animator animator) {

            }
        });
        mAnimExpandHint.setDuration(ignoreHintArea ? 0 : mPerAnimDuration);
    }

    /**
     * 设置初始值
     *
     * @param context
     */
    private void initDefaultValue(Context context) {
        mGapBetweenCircle = 85;


        isAddFillMode = true;
        mAddEnableBgColor = 0xFFFFDC5B;
        mAddEnableFgColor = Color.BLACK;
        mAddDisableBgColor = 0xff979797;
        mAddDisableFgColor = Color.BLACK;

        isDelFillMode = false;
        mDelEnableBgColor = 0xff979797;
        mDelEnableFgColor = 0xff979797;
        mDelDisableBgColor = 0xff979797;
        mDelDisableFgColor = 0xff979797;

/*        mMaxCount = 4;
        mCount = 1;*/

        mRadius = 31.25f;
        mCircleWidth = 2.5f;
        mLineWidth = 5f;
        mTextSize = 36.35f;

        mHintText = "加入购物车";
        mHintBgColor = mAddEnableBgColor;
        mHintFgColor = mAddEnableFgColor;
        mHingTextSize = 30;
        mHintBgRoundValue = 12;

        mReplenishText = "补货中";
        mReplenishTextColor = 0xfff32d3b;
        mReplenishTextSize = mHingTextSize;

    }

    @Override
    public boolean onEstimateSize(int widthMeasureSpec, int heightMeasureSpec) {
        int wMode = EstimateSpec.getMode(widthMeasureSpec);
        int wSize = EstimateSpec.getSize(widthMeasureSpec);
        int hMode = EstimateSpec.getMode(heightMeasureSpec);
        int hSize = EstimateSpec.getSize(heightMeasureSpec);
        switch (wMode) {
            case EstimateSpec.PRECISE:
                break;
            case EstimateSpec.NOT_EXCEED:
                //不超过父控件给的范围内，自由发挥
                int computeSize = (int) (getPaddingLeft() + mRadius * 2
                        + mGapBetweenCircle
                        + mRadius * 2 + getPaddingRight() + mCircleWidth * 2);
                wSize = computeSize < wSize ? computeSize : wSize;
                break;
            case EstimateSpec.UNCONSTRAINT:
                //自由发挥
                computeSize = (int) (getPaddingLeft()
                        + mRadius * 2 + mGapBetweenCircle
                        + mRadius * 2 + getPaddingRight() + mCircleWidth * 2);
                wSize = computeSize;
                break;
        }
        switch (hMode) {
            case EstimateSpec.PRECISE:
                break;
            case EstimateSpec.NOT_EXCEED:
                int computeSize = (int) (getPaddingTop()
                        + mRadius * 2 + getPaddingBottom() + mCircleWidth * 2);
                hSize = computeSize < hSize ? computeSize : hSize;
                break;
            case EstimateSpec.UNCONSTRAINT:
                computeSize = (int) (getPaddingTop()
                        + mRadius * 2 + getPaddingBottom() + mCircleWidth * 2);
                hSize = computeSize;
                break;
        }
        setEstimatedSize(EstimateSpec
                        .getSizeWithMode(wSize, EstimateSpec.NOT_EXCEED),
                EstimateSpec.getSizeWithMode(hSize, EstimateSpec.NOT_EXCEED));

        //先暂停所有动画
        cancelAllAnim();
        //复用时会走这里，所以初始化一些UI显示的参数
        initAnimSettingsByCount();
        return true;
    }

    /**
     * 根据当前count数量 初始化 hint提示语相关变量
     */
    private void initAnimSettingsByCount() {
        if (mCount == 0) {
            // 0 不显示 数字和-号
            mAnimFraction = 1;
        } else {
            mAnimFraction = 0;
        }

        if (mCount == 0) {
            isHintMode = true;
            isShowHintText = true;
            mAnimExpandHintFraction = 0;
        } else {
            isHintMode = false;
            isShowHintText = false;
            mAnimExpandHintFraction = 1;
        }
    }

    @Override
    public void onRefreshed(Component component) {
        mLeft = (int) (getPaddingLeft() + mCircleWidth);
        mTop = (int) (getPaddingTop() + mCircleWidth);
        mWidth = getWidth();
        mHeight = getHeight();
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        onRefreshed(component);
        if (isReplenish) {
            // 计算Baseline绘制的起点X轴坐标
            float baseX = mWidth / 2 - mReplenishPaint.measureText(mReplenishText) / 2;
            // 计算Baseline绘制的Y坐标
            float baseY = (mHeight / 2)
                    - ((mReplenishPaint.descent() + mReplenishPaint.ascent()) / 2);
            canvas.drawText(mReplenishPaint, mReplenishText, baseX, baseY);
            return;
        }


        if (!ignoreHintArea && isHintMode) {
            //add hint 展开动画
            //if (mCount == 0) {
            //背景
            mHintPaint.setColor(new Color(mHintBgColor));
            RectFloat rectF = new RectFloat(mLeft
                    + (mWidth - mRadius * 2) * mAnimExpandHintFraction, mTop
                    , mWidth - mCircleWidth, mHeight - mCircleWidth);
            canvas.drawRoundRect(rectF, mHintBgRoundValue, mHintBgRoundValue, mHintPaint);
            if (isShowHintText) {
                //前景文字
                mHintPaint.setColor(mHintFgColor);
                // 计算Baseline绘制的起点X轴坐标
                int baseX = (int) (mWidth / 2 - mHintPaint.measureText(mHintText) / 2);
                // 计算Baseline绘制的Y坐标
                int baseY = (int) ((mHeight / 2)
                        - ((mHintPaint.descent() + mHintPaint.ascent()) / 2));
                canvas.drawText(mHintPaint, mHintText, baseX, baseY);
            }
            //}
        } else {

            //动画 mAnimFraction ：减 0~1, 加 1~0 ,
            //动画位移Max,
            float animOffsetMax = (mRadius * 2 + mGapBetweenCircle);
            //透明度动画的基准
            int animAlphaMax = 255;
            int animRotateMax = 360;

            //左边
            //背景 圆
            if (mCount > 0) {
                mDelPaint.setColor(new Color(mDelEnableBgColor));
            } else {
                mDelPaint.setColor(new Color(mDelDisableBgColor));
            }
            mDelPaint.setAlpha((int) (animAlphaMax * (1 - mAnimFraction)));

            mDelPaint.setStrokeWidth(mCircleWidth);
            mDelPath.reset();
            //改变圆心的X坐标，实现位移
            mDelPath.addCircle(animOffsetMax * mAnimFraction
                    + mLeft + mRadius, mTop + mRadius, mRadius, Path.Direction.CLOCK_WISE);
            mDelRegion.setPath(mDelPath,
                    new Region(new Rect(mLeft, mTop, mWidth - getPaddingRight(),
                            mHeight - getPaddingBottom())));
            //canvas.drawCircle(mAnimOffset + mLeft + mRadius, mTop + mRadius, mRadius, mPaint);
            canvas.drawPath(mDelPath, mDelPaint);

            //前景 -
            if (mCount > 0) {
                mDelPaint.setColor(new Color(mDelEnableFgColor));
            } else {
                mDelPaint.setColor(new Color(mDelDisableFgColor));
            }
            mDelPaint.setStrokeWidth(mLineWidth);
            //旋转动画
            canvas.save();
            canvas.translate(animOffsetMax * mAnimFraction
                    + mLeft + mRadius, mTop + mRadius);
            canvas.rotate((int) (animRotateMax * (1 - mAnimFraction)));
        /*canvas.drawLine(mAnimOffset + mLeft + mRadius / 2, mTop + mRadius,
                mAnimOffset + mLeft + mRadius / 2 + mRadius, mTop + mRadius,
                mPaint);*/
            canvas.drawLine(-mRadius / 2, 0,
                    +mRadius / 2, 0,
                    mDelPaint);
            canvas.restore();


            //数量
            canvas.save();
            //平移动画
            canvas.translate(mAnimFraction * (/*mGap*/mGapBetweenCircle / 2
                    - mTextPaint.measureText(mCount + "") / 2 + mRadius), 0);
            //旋转动画,旋转中心点，x 是绘图中心,y 是控件中心
            canvas.rotate(360 * mAnimFraction,
                    /*mGap*/ mGapBetweenCircle / 2 + mLeft + mRadius * 2,
                    mTop + mRadius);
            //透明度动画
            mTextPaint.setAlpha((int) (255 * (1 - mAnimFraction)));
            //是没有动画的普通写法,x left, y baseLine
            canvas.drawText(mTextPaint, mCount + "",
                    /*mGap*/ mGapBetweenCircle / 2 - mTextPaint.measureText(mCount + "") / 2
                            + mLeft + mRadius * 2, mTop + mRadius
                            - (mFontMetrics.top + mFontMetrics.bottom) / 2);
            canvas.restore();

            //右边
            //背景 圆
            if (mCount < mMaxCount) {
                mAddPaint.setColor(new Color(mAddEnableBgColor));
            } else {
                mAddPaint.setColor(new Color(mAddDisableBgColor));
            }
            mAddPaint.setStrokeWidth(mCircleWidth);
            float left = mLeft + mRadius * 2 + mGapBetweenCircle;
            mAddPath.reset();
            mAddPath.addCircle(left + mRadius, mTop + mRadius, mRadius, Path.Direction.CLOCK_WISE);
            mAddRegion.setPath(mAddPath, new Region(
                    new Rect(mLeft, mTop, mWidth - getPaddingRight(), mHeight - getPaddingBottom())));
            //canvas.drawCircle(left + mRadius, mTop + mRadius, mRadius, mPaint);
            canvas.drawPath(mAddPath, mAddPaint);
            //前景 +
            if (mCount < mMaxCount) {
                mAddPaint.setColor(mAddEnableFgColor);
            } else {
                mAddPaint.setColor(mAddDisableFgColor);
            }
            mAddPaint.setStrokeWidth(mLineWidth);
            canvas.drawLine(left + mRadius / 2, mTop + mRadius,
                    left + mRadius / 2 + mRadius, mTop + mRadius, mAddPaint);
            canvas.drawLine(left + mRadius, mTop + mRadius / 2,
                    left + mRadius, mTop + mRadius / 2 + mRadius, mAddPaint);
        }
    }

    @Override
    public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
        int action = touchEvent.getAction();
        switch (action) {
            case TouchEvent.PRIMARY_POINT_DOWN:
                if (isReplenish) {
                    break;
                }
                //hint文字模式
                if (isHintMode) {
                    onAddClick();
                    return true;
                } else {
                    if (mAddRegion.contains((int)
                                    touchEvent.getPointerPosition(touchEvent.getIndex()).getX(),
                            (int) touchEvent.getPointerPosition(touchEvent.getIndex()).getY())) {
                        onAddClick();
                        return true;
                    } else if (mDelRegion.contains((int)
                                    touchEvent.getPointerPosition(touchEvent.getIndex()).getX(),
                            (int) touchEvent.getPointerPosition(touchEvent.getIndex()).getY())) {
                        onDelClick();
                        return true;
                    }
                }
                break;
            case TouchEvent.POINT_MOVE:
                break;
            case TouchEvent.PRIMARY_POINT_UP:
            case TouchEvent.CANCEL:
                break;
        }

        return true;
    }

    /**
     * 使用时，可以重写`onDelClick()`和` onAddClick()`方法，
     * 并在合适的时机回调`onCountAddSuccess()`和` onCountDelSuccess()`以执行动画。
     */
    protected void onDelClick() {
        if (mCount > 0) {
            mCount--;
            onCountDelSuccess();
            if (null != mOnAddDelListener) {
                mOnAddDelListener.onDelSuccess(mCount);
            }
        } else {
            if (null != mOnAddDelListener) {
                mOnAddDelListener.onDelFaild(mCount,
                        IOnAddDelListener.FailType.COUNT_MIN);
            }
        }

    }

    protected void onAddClick() {
        if (mCount < mMaxCount) {
            mCount++;
            onCountAddSuccess();
            if (null != mOnAddDelListener) {
                mOnAddDelListener.onAddSuccess(mCount);
            }
        } else {
            if (null != mOnAddDelListener) {
                mOnAddDelListener.onAddFailed(mCount, IOnAddDelListener.FailType.COUNT_MAX);
            }
        }
    }

    /**
     * 数量增加成功后，使用者回调以执行动画。
     */
    public void onCountAddSuccess() {
        if (mCount == 1) {
            cancelAllAnim();
            mAnimReduceHint.start();
        } else {
            mAnimFraction = 0;
            invalidate();
        }
    }

    /**
     * 数量减少成功后，使用者回调以执行动画。
     */
    public void onCountDelSuccess() {
        if (mCount == 0) {
            cancelAllAnim();
            mAniDel.start();
        } else {
            mAnimFraction = 0;
            invalidate();
        }
    }
}
